#ifndef __C_KERNEL_SLAB_H__
#define __C_KERNEL_SLAB_H__

#include "std/list.h"
#include "std/avltree.h"
#include "kernel/spinlock.h"

#ifdef __cplusplus
extern "C" {
#endif

#define KMEM_CACHE_NAME_MAX_LEN		(16)
#define MIN_KMEM_CACHE_NODE_SIZE	(16)
#define KMEM_CACHE_NODE_ALIGNMENT	(4)

typedef struct kmem_cache
{
	char name[KMEM_CACHE_NAME_MAX_LEN];

	listnode_t ownerlist;
	listnode_t slabs_partial;
	listnode_t slabs_empty;
	listnode_t slabs_full;

	spinlock_t spinlock;

	uint pages;				// number of pages in one slab
	uint objects;			// number of objects in one slab
	uint size;				// size of the object
	uint coloroff;			// color off for slab

	void (*ctor)(struct kmem_cache* cache, void* buf, size_t sz);
	void (*dtor)(struct kmem_cache* cache, void* buf, size_t sz);
}
kmem_cache_t;

typedef struct slab_freelist_node
{
	struct slab_freelist_node *next;
}
slab_freelist_node_t;

typedef struct slab
{
	listnode_t ownerlist;
	avl_node_t avlnode;

	kmem_cache_t *mcache;
	void* buffer;
	uint  first;
	slab_freelist_node_t freelist;

	// items that has been allocated
	uint  used;
}
slab_t;

// global initialization
void global_init_kmem_cache_module(void);

// create a new kmem_cache
kmem_cache_t* easy_kmem_cache_create(char* name, size_t sz,
		void (*ctor)(kmem_cache_t*, void*, size_t),
		void (*dtor)(kmem_cache_t*, void*, size_t));

// flags
// this means the slab structure
// will be contained in the data area
#define KMEM_CACHE_COMPACT		(1)

// create a new kmem_cache
kmem_cache_t* kmem_cache_create(char *name, size_t sz,
		size_t max_items_per_slab, uint flags,
		void (*ctor)(kmem_cache_t*, void*, size_t),
		void (*dtor)(kmem_cache_t*, void*, size_t));

// allocate a cache from kmem_cache
void* kmem_cache_alloc(kmem_cache_t *cache);

// free a cache to kmem_cache
void kmem_cache_free(void *p);

// kernel malloc
void* kmalloc(size_t sz);

// kernel free
#define kfree(p)	kmem_cache_free(p)

#ifdef __cplusplus
}
#endif
#endif
/* EOF */
